﻿using Autofac;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Data;
using System.Security.Cryptography;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Filters;
using System.Reflection;
using Simple.Web.Common.autofac;
using Simple.Web.Common.logger;
using Simple.Common;
using Simple.Web.Common;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;


namespace Simple.Web.Core
{
	/// <summary>
	/// 
	/// </summary>
	public class Startup
	{
		/// <summary>
		/// 
		/// </summary>
		public string DefaultCorsPolicyName = "defaultCors";
		/// <summary>
		/// 
		/// </summary>
		/// <param name="configuration"></param>
		public Startup(IConfiguration configuration)
		{
			Configuration = configuration;
		}
		/// <summary>
		/// 
		/// </summary>
		public IConfiguration Configuration { get; }


		// This method gets called by the runtime. Use this method to add services to the container.
		/// <summary>
		/// 
		/// </summary>
		/// <param name="services"></param>
		public void ConfigureServices(IServiceCollection services)
		{

			services.AddControllers();

			#region swagger
			services.AddSwaggerGen(c =>
			{
				c.SwaggerDoc("v1", new OpenApiInfo { Title = "Simple.Web.Core", Version = "v1" });


				c.OperationFilter<AddResponseHeadersFilter>();
				c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();

				c.OperationFilter<SecurityRequirementsOperationFilter>();

				// 定义安全定义
				c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
				{
					Description = "JWT Authorization header using the Bearer scheme",
					Name = "Authorization",
					In = ParameterLocation.Header,
					Type = SecuritySchemeType.ApiKey,
					Scheme = "Bearer"
				});

				// 添加认证要求
				c.AddSecurityRequirement(
					new OpenApiSecurityRequirement{
						{
							new OpenApiSecurityScheme{
								Reference = new OpenApiReference	{
									Type = ReferenceType.SecurityScheme,	Id = "Bearer"	}},
							Array.Empty<string>()	
						}});




				var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
				var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
				c.IncludeXmlComments(xmlPath, true);
			});
			#endregion


			#region 跨域

			services.AddCors(options =>
			{
				options.AddPolicy(DefaultCorsPolicyName, builder =>
				{
					var CorsOrigins = Configuration.GetSection("CorsOrigins").Get<string[]>();

					builder.WithOrigins(CorsOrigins)
						.AllowAnyMethod()
						.AllowAnyHeader()
						.SetIsOriginAllowed(_ => true) // =AllowAnyOrigin()
						.AllowCredentials();

				}
				);
			}
			);
			#endregion


			#region filter

			services.AddControllersWithViews(options =>
			{
				options.Filters.Add<SimpleExceptionAttributer>();
			});

			#endregion

			#region replace ControllerActivator
			services.Replace(ServiceDescriptor.Transient<IControllerActivator
			   , ServiceBasedControllerActivator>());
			#endregion

			services.AddSerilog();

			services.Configure<ApiBehaviorOptions>((o) =>
			{
				o.SuppressModelStateInvalidFilter = false;
			});


			#region 注册Jwt认证
			services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer("Bearer", o =>
			{
				o.TokenValidationParameters = new TokenValidationParameters
				{
					ValidateIssuerSigningKey = true,//是否验证签名,不验证的画可以篡改数据，不安全
					IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetValue<string>("JwtTokenOptions:SecurityKey"))),//解密的密钥
					ValidateIssuer = true,//是否验证发行人，就是验证载荷中的Iss是否对应ValidIssuer参数
					ValidIssuer = Configuration.GetValue<string>("JwtTokenOptions:Issuer"),//发行人,
					ValidateAudience = true,//是否验证订阅人，就是验证载荷中的Aud是否对应ValidAudience参数
					ValidAudience = Configuration.GetValue<string>("JwtTokenOptions:Audience")//订阅人       
				};
			});
			services.AddAuthorization();
			#endregion

		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="containerBuilder"></param>
		public void ConfigureContainer(ContainerBuilder containerBuilder)
		{
			#region autofac 
			Type[] controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
		  .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();


			containerBuilder.RegisterTypes(controllersTypesInAssembly).
				PropertiesAutowired(new AutowiredPropertySelector());
			#endregion

			#region aop
			containerBuilder.RegisterType<CustomAutofacAop>().PropertiesAutowired(new AutowiredPropertySelector());
			#endregion

			containerBuilder.RegisterDateBaseService();

			containerBuilder.RegisterToolService();

		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="app"></param>
		/// <param name="env"></param>
		public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
		{
			// 配置HTTP请求管道
			if (env.IsDevelopment())
			{
				app.UseDeveloperExceptionPage();
			}

			app.UseAuthentication();

			app.UseSwagger();

			app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Simple.Web.Core v1"));

			app.UseRouting();

			app.UseAuthorization();

			app.UseEndpoints(endpoints =>
			{
				endpoints.MapControllers();
			});
		}
	}
}
